package org.cybzacg.encryption.strategy.impl;

import org.cybzacg.encryption.strategy.SecurityStrategy;
import org.cybzacg.encryption.context.EncryptionContext;
import org.cybzacg.encryption.model.EncryptionResult;
import org.cybzacg.encryption.model.ValidationResult;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionStatus;
import org.cybzacg.encryption.enums.SecurityStrategyEnum;
import org.cybzacg.encryption.exception.EncryptionException;

import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * 严格安全策略实现
 * 提供最高级别的安全验证和处理
 * 
 * @author encryption team
 * @version 1.0
 */
public class StrictSecurityStrategy implements SecurityStrategy {

    private static final int MIN_KEY_SIZE = 256; // 最小密钥长度（位）
    private static final int MAX_DATA_SIZE = 1024 * 1024; // 最大数据大小（1MB）
    private static final long MAX_PROCESSING_TIME = 30000; // 最大处理时间（30秒）

    @Override
    public SecurityStrategyEnum getStrategyType() {
        return SecurityStrategyEnum.STRICT;
    }

    @Override
    public ValidationResult validateBeforeEncryption(byte[] data, EncryptionContext context) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();

        // 验证数据
        if (data == null) {
            errors.add("Data cannot be null");
        } else {
            // 检查数据大小
            if (data.length > MAX_DATA_SIZE) {
                errors.add("Data size exceeds maximum limit: " + data.length + " bytes (max: " + MAX_DATA_SIZE + ")");
            }

            // 检查数据是否为空
            if (data.length == 0) {
                errors.add("Data cannot be empty");
            }

            // 检查数据模式（简单的熵检查）
            if (hasLowEntropy(data)) {
                warnings.add("Data has low entropy, may be predictable");
            }
        }

        // 验证上下文
        ValidationResult contextValidation = validateContext(context);
        errors.addAll(contextValidation.getErrors());
        warnings.addAll(contextValidation.getWarnings());

        // 返回结果
        if (!errors.isEmpty()) {
            return ValidationResult.failure("Strict security validation failed", errors, context);
        } else if (!warnings.isEmpty()) {
            return ValidationResult.withWarnings("Strict security validation passed with warnings", warnings, context);
        } else {
            return ValidationResult.success("Strict security validation passed", context);
        }
    }

    @Override
    public ValidationResult validateBeforeDecryption(byte[] encryptedData, EncryptionContext context) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();

        // 验证加密数据
        if (encryptedData == null) {
            errors.add("Encrypted data cannot be null");
        } else {
            // 检查数据大小
            if (encryptedData.length > MAX_DATA_SIZE) {
                errors.add("Encrypted data size exceeds maximum limit: " + encryptedData.length + " bytes (max: "
                        + MAX_DATA_SIZE + ")");
            }

            // 检查数据是否为空
            if (encryptedData.length == 0) {
                errors.add("Encrypted data cannot be empty");
            }

            // 检查数据格式（应该看起来像随机数据）
            if (hasLowEntropy(encryptedData)) {
                errors.add("Encrypted data has low entropy, may be corrupted or not properly encrypted");
            }
        }

        // 验证上下文
        ValidationResult contextValidation = validateContext(context);
        errors.addAll(contextValidation.getErrors());
        warnings.addAll(contextValidation.getWarnings());

        // 返回结果
        if (!errors.isEmpty()) {
            return ValidationResult.failure("Strict security validation failed", errors, context);
        } else if (!warnings.isEmpty()) {
            return ValidationResult.withWarnings("Strict security validation passed with warnings", warnings, context);
        } else {
            return ValidationResult.success("Strict security validation passed", context);
        }
    }

    @Override
    public EncryptionResult processEncryptionResult(EncryptionResult result, EncryptionContext context) {
        if (!result.isSuccess()) {
            return result;
        }

        // 严格模式下的额外验证
        byte[] encryptedData = result.getData();
        if (encryptedData != null) {
            // 验证加密后的数据
            if (hasLowEntropy(encryptedData)) {
                return EncryptionResult.error(
                        new EncryptionException("Encrypted data has insufficient entropy"),
                        context);
            }

            // 验证数据大小合理性
            EncryptionAlgorithm algorithm = context.getAlgorithm();
            if (algorithm != null) {
                int expectedMinSize = getMinimumEncryptedSize(algorithm, context);
                if (encryptedData.length < expectedMinSize) {
                    return EncryptionResult.error(
                            new EncryptionException("Encrypted data size is too small for algorithm"),
                            context);
                }
            }
        }

        return result;
    }

    @Override
    public EncryptionResult processDecryptionResult(EncryptionResult result, EncryptionContext context) {
        if (!result.isSuccess()) {
            return result;
        }

        // 严格模式下的额外验证
        byte[] decryptedData = result.getData();
        if (decryptedData != null) {
            // 验证解密后的数据完整性
            if (decryptedData.length == 0) {
                return EncryptionResult.error(
                        new EncryptionException("Decrypted data is empty"),
                        context);
            }

            // 可以添加更多验证，如格式检查、签名验证等
        }

        return result;
    }

    @Override
    public Exception handleException(Exception exception, EncryptionContext context) {
        // 严格模式下，所有异常都需要处理
        if (exception instanceof EncryptionException) {
            EncryptionException encEx = (EncryptionException) exception;
            if (encEx.getMessage() != null && encEx.getMessage().contains("configuration")) {
                // 配置错误，不重试
                return exception;
            }
        }

        // 其他异常可以考虑重试
        return exception;
    }

    @Override
    public String getDescription() {
        return "Strict security strategy with maximum security validation";
    }

    @Override
    public boolean supports(EncryptionContext context) {
        if (context == null) {
            return false;
        }

        // 严格模式支持所有有效的上下文
        return context.isValid();
    }

    @Override
    public int getPriority() {
        return 10; // 最高优先级
    }

    /**
     * 检查算法是否被允许
     */
    private boolean isAlgorithmAllowed(EncryptionAlgorithm algorithm) {
        if (algorithm == null) {
            return false;
        }

        // 严格模式下只允许强加密算法
        switch (algorithm) {
            case AES:
            case RSA:
            case SHA256:
            case SHA384:
            case SHA512:
            case BLOWFISH:
            case TWOFISH:
                return true;
            default:
                return false;
        }
    }

    /**
     * 验证上下文
     */
    private ValidationResult validateContext(EncryptionContext context) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();

        if (context == null) {
            errors.add("Context cannot be null");
            return ValidationResult.failure("Context validation failed", errors, context);
        }

        // 验证算法
        EncryptionAlgorithm algorithm = context.getAlgorithm();
        if (algorithm == null) {
            errors.add("Algorithm cannot be null");
        } else {
            if (!isAlgorithmAllowed(algorithm)) {
                errors.add("Algorithm not allowed in strict mode: " + algorithm);
            }

            // 验证密钥长度
            if (context.getKey() != null) {
                int keySizeBits = context.getKey().length * 8;
                if (keySizeBits < MIN_KEY_SIZE) {
                    errors.add(
                            "Key size too small for strict mode: " + keySizeBits + " bits (min: " + MIN_KEY_SIZE + ")");
                }
            }
        }

        // 验证超时设置
        if (context.getTimeout() > 0 && context.getTimeout() > MAX_PROCESSING_TIME) {
            warnings.add("Timeout is very large, may cause performance issues");
        }

        if (!errors.isEmpty()) {
            return ValidationResult.failure("Context validation failed", errors, context);
        } else if (!warnings.isEmpty()) {
            return ValidationResult.withWarnings("Context validation passed with warnings", warnings, context);
        } else {
            return ValidationResult.success("Context validation passed", context);
        }
    }

    /**
     * 检查数据是否具有低熵
     * 
     * <p>
     * 使用 HashSet 统计唯一字节数，时间复杂度 O(n)
     * 
     * @param data 待检查的数据
     * @return 是否为低熵数据
     */
    private boolean hasLowEntropy(byte[] data) {
        if (data == null || data.length < 8) {
            return true;
        }

        // 使用 Set 统计唯一字节数 - O(n) 复杂度
        Set<Byte> uniqueBytes = new HashSet<>();
        for (byte b : data) {
            uniqueBytes.add(b);
        }

        // 如果唯一字节数量少于总数的25%，认为是低熵
        double uniquenessRatio = (double) uniqueBytes.size() / data.length;
        return uniquenessRatio < 0.25;
    }

    /**
     * 获取算法的最小加密数据大小
     */
    private int getMinimumEncryptedSize(EncryptionAlgorithm algorithm, EncryptionContext context) {
        switch (algorithm) {
            case AES:
                // AES块大小为16字节，至少应该有一个块
                return 16;
            case RSA:
                // RSA加密数据大小取决于密钥长度
                if (context.getKey() != null) {
                    return context.getKey().length;
                }
                return 128; // 默认1024位
            default:
                return 16; // 默认最小值
        }
    }
}
